// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Min_sphere_d.cpp 167 2007-11-02 15:36:54Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Geometric_Optimisation/Py_Min_sphere_d.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

// include ====================================================================
#include <CGAL/basic.h>
#include <include/Kernels.h>

#include <CGAL/Min_sphere_d.h>
#include <CGAL/Optimisation_d_traits_2.h>
#include <CGAL/Optimisation_d_traits_3.h>

#include <include/iterator.h>
#include <boost/python.hpp>
#include <boost/cstdint.hpp>
#include <list>
#include "Py_Min_sphere_d_doc.h"

// Using =======================================================================
using namespace boost::python;


template < class Traits >
class Min_sphere : public CGAL::Min_sphere_d<Traits>
{
	public:
		typedef typename CGAL::Min_sphere_d<Traits> 			Min_sphere_d;
		typedef typename Min_sphere_d::Point 					Point;
		typedef typename Min_sphere_d::Point_iterator 			Point_iterator;
		typedef typename Min_sphere_d::Support_point_iterator 	Support_point_iterator;
		Min_sphere():Min_sphere_d(){};
		Min_sphere(const Min_sphere& msph):Min_sphere_d(msph){}
		Min_sphere(const Traits& traits):Min_sphere_d(traits){}
		void insert_list(const boost::python::list& pts)
		{
			int N = boost::python::extract<int>(pts.attr("__len__")());
			for(int i = 0 ; i < N ; i++)
			{
				Point P = boost::python::extract<Point>(pts[i]); 
				this->insert(P);
			}
		}
		void insert(const Point& P){Min_sphere_d::insert(P);}
		
		bool is_valid( bool verbose = false, int level = 0) const
		{
			return this->Min_sphere_d::is_valid(verbose,level);
		}

		simple_python_iterator<Point_iterator> points()
		{
			std::pair< Point_iterator , Point_iterator > p( this->points_begin(), this->points_end() );
			return simple_python_iterator<Point_iterator>(p);
		}
		simple_python_iterator<Support_point_iterator> support_points()
		{
			std::pair< Support_point_iterator , Support_point_iterator > p( this->support_points_begin(), this->support_points_end() );
			return simple_python_iterator<Support_point_iterator>(p);
		}
	private:
		

};
// Declarations ================================================================
namespace  {

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(traits_2_is_valid_overloads_0_2, is_valid, 0, 2)
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(traits_3_is_valid_overloads_0_2, is_valid, 0, 2)

}// namespace 

template<class kernel>
void Py_Min_sphere_d()
{
	typedef typename kernel::Point_2 Point_2;
	typedef typename kernel::Point_3 Point_3;

	typedef CGAL::Optimisation_d_traits_2<kernel> traits_2;
	typedef CGAL::Optimisation_d_traits_3<kernel> traits_3;
	typedef Min_sphere<traits_2> Min_sphere_2;
	typedef Min_sphere<traits_3> Min_sphere_3;

	typedef typename Min_sphere_3::Point_iterator 			Point_iterator;
	typedef typename Min_sphere_3::Support_point_iterator 	Support_point_iterator;

    class_< Min_sphere_2 >("Min_sphere_2", Min_sphere_2_doc,init<  >())
        .def(init< const Min_sphere_2& >(Min_sphere_init_2_doc))
        .def("number_of_points", &Min_sphere_2::number_of_points,Min_sphere_number_of_points_doc)
        .def("number_of_support_points", &Min_sphere_2::number_of_support_points,Min_sphere_number_of_support_points_doc)
	.def("insert",&Min_sphere_2::insert_list)
	.def("insert",(void  (Min_sphere_2::*)(const Point_2&))&Min_sphere_2::insert,Min_sphere_insert_doc)
        .def("ambient_dimension", &Min_sphere_2::ambient_dimension,Min_sphere_ambient_dimension_doc)
        .def("center", &Min_sphere_2::center,Min_sphere_center_doc)
        .def("squared_radius", &Min_sphere_2::squared_radius,Min_sphere_squared_radius_doc)
        .def("bounded_side", &Min_sphere_2::bounded_side,Min_sphere_bounded_side_doc)
        .def("has_on_bounded_side", &Min_sphere_2::has_on_bounded_side,Min_sphere_has_on_bounded_side_doc)
        .def("has_on_unbounded_side", &Min_sphere_2::has_on_unbounded_side,Min_sphere_has_on_unbounded_side_doc)
        .def("has_on_boundary", &Min_sphere_2::has_on_boundary,Min_sphere_has_on_boundary_doc)
        .def("is_empty", &Min_sphere_2::is_empty,Min_sphere_is_empty_doc)
        .def("is_degenerate", &Min_sphere_2::is_degenerate,Min_sphere_is_degenerate_doc)
        .def("clear", &Min_sphere_2::clear,Min_sphere_clear_doc)
        .def("is_valid", &Min_sphere_2::is_valid, traits_2_is_valid_overloads_0_2(Min_sphere_is_valid_doc))
	.add_property("points",&Min_sphere_2::points)
	.add_property("support_points",&Min_sphere_2::support_points)
    ;


    class_< Min_sphere_3 >("Min_sphere_3",Min_sphere_3_doc, init<  >())
        .def(init< const Min_sphere_3& >(Min_sphere_init_3_doc))
        .def("number_of_points", &Min_sphere_3::number_of_points,Min_sphere_number_of_points_doc)
        .def("number_of_support_points", &Min_sphere_3::number_of_support_points,Min_sphere_number_of_support_points_doc)
	.def("insert",&Min_sphere_3::insert_list)
	.def("insert",(void  (Min_sphere_3::*)(const Point_3&))&Min_sphere_3::insert,Min_sphere_insert_doc)
        .def("ambient_dimension", &Min_sphere_3::ambient_dimension,Min_sphere_ambient_dimension_doc)
        .def("center", &Min_sphere_3::center,Min_sphere_center_doc)
        .def("squared_radius", &Min_sphere_3::squared_radius,Min_sphere_squared_radius_doc)
        .def("bounded_side", &Min_sphere_3::bounded_side,Min_sphere_bounded_side_doc)
        .def("has_on_bounded_side", &Min_sphere_3::has_on_bounded_side,Min_sphere_has_on_bounded_side_doc)
        .def("has_on_unbounded_side", &Min_sphere_3::has_on_unbounded_side,Min_sphere_has_on_unbounded_side_doc)
        .def("has_on_boundary", &Min_sphere_3::has_on_boundary,Min_sphere_has_on_boundary_doc)
        .def("is_empty", &Min_sphere_3::is_empty,Min_sphere_is_empty_doc)
        .def("is_degenerate", &Min_sphere_3::is_degenerate,Min_sphere_is_degenerate_doc)
        .def("clear", &Min_sphere_3::clear,Min_sphere_clear_doc)
        .def("is_valid", &Min_sphere_3::is_valid, traits_3_is_valid_overloads_0_2(Min_sphere_is_valid_doc))
	.add_property("points",&Min_sphere_3::points)
	.add_property("support_points",&Min_sphere_3::support_points)
    ;

	simple_python_iterator<Point_iterator>::declare("Point_iterator","An iterator that enumerates the Points in a Min_sphere");
	simple_python_iterator<Support_point_iterator>::declare("Support_point_iterator","An iterator that enumerates the support Points in a Min_sphere");

}

void export_Min_sphere_d()
{
	Py_Min_sphere_d<K>();
}
